Dart 变量

2023/5/11

# Dart 变量

下面的示例代码将创建一个变量并将其初始化:

var name = 'Bob';
1

变量仅存储对象的引用。这里名为 name 的变量存储了一个 String 类型对象的引用,"Bob" 则是该对象的值。

name 变量的类型被推断为 String,除了用 var 关键字以 推断类型的方式 创建变量,还可以以 指定类型的方式 创建变量:

String name = 'Bob';
1

如果一个对象的引用不局限于单一的类型,可以将其指定为 Object(或 dynamic)类型:

Object name = 'Bob';
1

# 默认值

在 Dart 中,未初始化以及可空类型的变量拥有一个默认的初始值 null。(如果你未迁移至空安全,所有变量都为可空类型。)即便数字也是如此,因为在 Dart 中一切皆为对象,数字也不例外:

int? lineCount;
assert(lineCount == null);
1
2

若你启用了空安全,你必须在使用它前初始化它的值

int lineCount = 0;
1

你并不需要在声明变量时初始化,只需要在第一次用到这个变量前初始化即可 (顶级变量以及类变量支持)。例如,下面的代码是正确的,因为 Dart 可以在 lineDart 被传递到 print() 时检测它是否为空:

int lineCount;

if (weLikeCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}

print(lineCount);
1
2
3
4
5
6
7
8
9

# 延迟初始化变量

late 修饰符可以在以下情况下使用:

  • 声明一个非空变量,但不在声明时初始化。
  • 延迟初始化一个变量。

通常 Dart 的语义分析会在一个已声明为非空的变量被使用前检查它是否已经被赋值,但有时这个分析会失败。例如:在检查顶级变量和实例变量时,分析通常无法判断它们是否已经被初始化,因此不会进行分析。

如果你确定这个变量在使用前就已经被声明,但 Dart 判断失误的话,你可以在声明变量的时候使用 late 修饰来解决这个问题:

late String description;

void main() {
  descriptioin = 'Lawrence';
  print(description);
}
1
2
3
4
5
6

⚠️若 late 标记的变量在使用前没有初始化,在变量被使用时会抛出运行时异常。

如果一个 late 修饰的变量在声明时就指定了初始化方法,那么它实际的初始化过程会发生在第一次被使用的时候。这样的延迟初始化在以下场景会带来便利:

  • Dart 认为这个变量可能在后文中没被使用,而且初始化时将产生较大的代价。
  • 你正在初始化一个实例变量,它的初始化方法需要调用 this

在下面这个例子中,如果 temperature 变量从未被使用的话,那么 readThermometer() 将永远不会被调用:

// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // 延迟初始化
1
2

# Final 和 Const

如果你不想更改一个变量,可以使用 final 或者 const 修饰变量,这两个关键字可以替代 var 关键字或者加在一个具体的类型前。一个 final 变量只可以被赋值一次;一个 const 变量是一个编译时常量(const 变量同时也是 final 的)。

实例变量可以是 final 的但不可以是 const。

下面的示例中我们创建并设置两个 final 变量:

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bob';
1
2

你不能修改一个 final 变量的值:

name = 'Alice'; // Error: a final variable can only be set once.
1

使用关键字 const 修饰变量表示该变量为 编译时常量。如果使用 const 修饰类中的变量,则必须加上 static 关键字,即 static const。在声明 const 变量时可以直接为其赋值,也可以使用其他的 const 变量为其赋值。

const bar = 1000000;
const double atm = 1.01325 * bar;
1
2

const 关键字不仅仅可以用来定义常量,还可以用来创建 常量值,该常量值可以赋予给任何变量。你也可以将构造函数声明为 const,这种类型的构造函数创建的 对象是不可改变的

var foo = const [];
final bar = const [];
const baz = []; // 等于 const []
1
2
3

如果使用初始化表达式为常量赋值可以省略掉关键字 const,比如上面的常量 baz 的赋值就省略掉了 const。

没有使用 final 或 const 修饰的变量的值是可以被更改的,即使这些变量之前引用过 const 的值。

foo = [1, 2, 3]; // was const []
1

常量的值不可以被修改:

baz = [42]; // Error: Constant variables can't be assigned a value.
1